#pragma once;

#include<iostream>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include<string>
using namespace std;


class UdpSocket
{
public:
    // 文件描述符下标从-1开始.
    UdpSocket()
      :fd_(-1)
    {}

    //创建socket
    bool Socket()
    {
        fd_ = socket(AF_INET, SOCK_DGRAM, 0);
        if(fd_ < 0)
        {
            perror("sock fail!");
            return false;
        }
        return true;
    }

    //关闭socket.
    bool Close()
    {
        close(fd_);
        return true;
    }

    //绑定socket
    bool Bind(const string& ip, uint16_t port)
    {
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_port = htons(port);
        int ret = bind(fd_, (sockaddr*)&addr, sizeof(addr));
        if(ret < 0)
        {
            perror("bind fail!");
            return false;
        }
        return true;
    }

    //接收消息:
    bool RecvForm(string* buff, string* ip = NULL, uint16_t* port = NULL)
    {
        char tem[1024 * 10] = {0};
        sockaddr_in peer;
        socklen_t len = sizeof(peer);
        ssize_t ret = recvfrom(fd_, tem, sizeof(tem) - 1, 0, (sockaddr*)&peer, &len);
        if(ret < 0)
        {
            perror("recv fail!");
            return false;
        }

        buff->assign(tem, ret);
        if(ip != NULL)
        {
            *ip = inet_ntoa(peer.sin_addr);
        }

        if(port != NULL)
        {
            *port = ntohs(peer.sin_port);
        }
        return true;
    }

    bool SendTo(const string* buff, const string& ip = NULL, uint16_t port = NULL)
    {
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_port = htons(port);

        ssize_t ret = sendto(fd_, buff, sizeof(buff) - 1, 0, (sockaddr*)&addr, sizeof(addr));
        if(ret < 0)
        {
            perror("sendto fail!");
            return false;
        }
        return true;
    }


private: 
    int fd_;
};